import os
import platform
import warnings
from browsermobproxy import Server
from selenium.common.exceptions import WebDriverException

from .. import webdriver
from .reuse_remote import ReuseRemote
from ..utils.ini_config_file import IniConfigFile
from ..common.__const__ import INI_PATH, TOOL_FLODER_PATH, ROOT_PATH, MESSAGE_DEBUG_SWITCH
# from ..CommonScripts.web_config import web_config, web_config_bl2, web_config_acpt, web_config_secondary, web_config_bl
from ..common.web_config import web_config, web_config_secondary
from ..report.log import logger
from ..utils.TimeMeta import TimeMeta
from qturboframe.lib.utils.CustomError.custom_error import CustomError
from qturboframe.lib.utils.CustomError.custom_exception import CustomException


class WebDriverFactory(TimeMeta):
    '''
    selenium统一入口

    :Attributes:
     - browser_type: 浏览器类型，默认是chrome
     - browser_id: 浏览器编号，根据编号区分打开的浏览器对象
     - precise: bool类型，是否预设代理，精准测试使用

    :Usage:
        通过driver的编号关联实例化对象关联的driver代理，对driver进行全局管理，
        允许多个浏览器通过不同的driver编号新建webdriver对象；
        对于不同的实例化对象使用相同的driver编号，访问的webdriver对象是同一个。
    '''

    _webdriver_path = None
    _binary_location = None
    _chrome_options = None
    _driver = None
    _server = None
    _proxy = None
    _proxy_switch = False

    def __init__(self, browser_type=None, browser_id='primary', precise=False):
        print(TOOL_FLODER_PATH)
        if not browser_type and os.path.exists(INI_PATH):
            browser_type = IniConfigFile(INI_PATH).read('Browser', 'browser_type')
        if not browser_type or browser_type.lower() not in ['ie','chrome','firefox']:
            browser_type = 'chrome'
        self.browser_type = browser_type
        web_config.driver_id = browser_id
        self.driver_url_no = 'driver_url_{}'.format(browser_id)
        self.driver_session_no = 'driver_session_{}'.format(browser_id)
        self.last_browser_type_no = 'last_browser_type_{}'.format(browser_id)
        self.last_browser_type = globals().get(self.last_browser_type_no)
        # self.server_no = 'server_{}'.format(browser_id)
        # self.proxy_no = 'proxy_{}'.format(browser_id)
        self.driver_no = 'driver_{}'.format(browser_id)
        self.__sync_info()
        # self.precise = precise
        # self._proxy_switch = self.precise

    def __sync_info(self):
        self.driver_url = globals().get(self.driver_url_no)
        self.driver_session = globals().get(self.driver_session_no)
        self.last_browser_type = globals().get(self.last_browser_type_no)
        # self._server = globals().get(self.server_no)
        # self._proxy = globals().get(self.proxy_no)
        self._driver = globals().get(self.driver_no)
        # web_config.is_web_proxy = self.is_proxy()

    def __start_proxy_server(self):
        warnings.warn("此方法已被废弃", DeprecationWarning);
        if self._proxy_switch:
            if not self._server:
                path = os.path.join(ROOT_PATH, "browsermob-proxy-2.1.4", "bin", "browsermob-proxy.bat")
                if len(self.get_proxy_list()) < 1:
                    options = {'port':8080}
                else:
                    options = {'port': 8081}
                self._server = Server(path, options)
                self._server.start()
                self._proxy = self._server.create_proxy()
                globals()[self.server_no] = self._server
                globals()[self.proxy_no] = self._proxy
                web_config.is_web_proxy = True
                if MESSAGE_DEBUG_SWITCH:
                    logger.debug('代理开启！')
            self._proxy_switch = False

    def __stop_proxy_server(self):
        warnings.warn("此方法已被废弃", DeprecationWarning);
        self._proxy_switch = self.precise
        if self._server is None:
            return
        self.__stop_proxy()
        self._server.stop()
        if MESSAGE_DEBUG_SWITCH:
            logger.debug('关闭代理服务！')
        globals().pop(self.server_no)
        globals().pop(self.proxy_no)

    def __stop_proxy(self):
        warnings.warn("此方法已被废弃", DeprecationWarning);
        if self._proxy is None:
            return
        self._proxy.close()
        web_config.is_web_proxy = False
        if MESSAGE_DEBUG_SWITCH:
            logger.debug('关闭代理！')

    def is_proxy(self):
        '''
        是否做了代理

        :return:
            做了代理返回True，否则返回False
        '''
        warnings.warn("此方法已被废弃", DeprecationWarning);
        if self._proxy:
            return True
        else:
            return False

    def set_proxy_har(self, ref=None, options=None, title=None):
        '''
        设置代理的HAR

        :Args:
         - ref: HAR的参考
         - options: 代理的关键配置，字典，三个关键key：captureHeaders、captureContent、captureBinaryContent，值为bool
         - title: 首页的标题
        :return:
        '''
        warnings.warn("此方法已被废弃", DeprecationWarning);
        if self._proxy is None:
            logger.warn('没有创建proxy，无法设置har！')
            return
        self._proxy.new_har(ref, options, title)
        if MESSAGE_DEBUG_SWITCH:
            logger.debug('设置代理har！')

    def get_proxy_har(self):
        '''
        获取代理的HAR
        '''
        warnings.warn("此方法已被废弃", DeprecationWarning);
        if self._proxy is None:
            logger.warn('没有创建proxy，获取不到har！')
            return None
        if MESSAGE_DEBUG_SWITCH:
            logger.debug('获取代理har！')
        return self._proxy.har

    def __create_driver(self, save_as=0, download=None, mobile_type=None,profile_dir=None):
        '''
        创建selenium的driver并打开代理服务

        :Args:
         - save_as: 另存为方式，默认值是0，静默保存
         - download: 保存的路径，默认使用浏览器默认保存路径
         - mobile_type: chrome的手机模式，默认为浏览器模式

        :Returns:
            返回driver对象，webdriver类型
        '''
        # 开启代理
        # self.__start_proxy_server()
        # if self._binary_location is None:
        #     # 读取浏览器安装路径
        #     if os.path.exists(INI_PATH):
        #         # browerbin用于指定浏览器程序路径
        #         try:
        #             self._binary_location = IniConfigFile(INI_PATH).read('Selenium', 'Browerbin')
        #         except:
        #             self._binary_location = None
        #     else:
        #         self._binary_location = None
        # # 设置浏览器安装路径
        # if self._binary_location:
        #     os.environ["webdriver.bin"] = self._binary_location
        # 设置并启动浏览器
        if self.browser_type.lower() == 'firefox':
            # 设置driver路径
            options = webdriver.FirefoxOptions
            if self._webdriver_path is None:
                # 判断系统是32bit还是64bit
                osbit = platform.architecture()[0]
                if osbit == '64bit':
                    exepath = os.path.join(TOOL_FLODER_PATH, r'firefox_x64', r'geckodriver.exe')
                else:
                    exepath = os.path.join(TOOL_FLODER_PATH, r'firefox_win32', r'geckodriver.exe')
                self._webdriver_path = os.path.abspath(exepath)
                os.environ["webdriver.driver"] = self._webdriver_path
            # 设置firefox下载路径
            profile = webdriver.FirefoxProfile(profile_dir)
            if download:
                profile.set_preference('browser.download.dir', download)
                profile.set_preference('browser.download.folderList', 2)
            else:
                profile.set_preference('browser.download.folderList', 1)
            profile.set_preference('browser.download.manager.showWhenStarting', False)
            if save_as == 0:
                profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/zip')
            _driver = webdriver.HSFirefox(firefox_profile=profile, firefox_binary=self._binary_location,
                                               executable_path=self._webdriver_path)
        elif self.browser_type.lower() == 'chrome':
            # 设置driver路径
            if self._webdriver_path is None:
                exepath = os.path.join(TOOL_FLODER_PATH, r'chromedriver', r'chromedriver.exe')
                self._webdriver_path = os.path.abspath(exepath)
                # os.environ["webdriver.driver"] = self._webdriver_path
            # 设置参数默认值
            if self._chrome_options is None:
                options = webdriver.ChromeOptions()
            else:
                options = self._chrome_options
            # chrome下载设置
            if save_as == 0:
                if download:
                    prefs = {'profile.default_content_settings.popups': 0,
                             'download.default_directory': download}
                else:
                    prefs = {'profile.default_content_settings.popups': 0}
            else:
                prefs = {'profile.default_content_settings.popups': 1}
            if not options.debugger_address:
                options.add_experimental_option('prefs', prefs)
                # 忽略chrome浏览器的提示语
                options.add_argument('disable-infobars')
                # 去掉不受支持的命令行标记
                options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors"])
            # 选择手机模式
            if mobile_type is not None:
                mobile_emulation = {"deviceName": mobile_type}
                options.add_experimental_option("mobileEmulation", mobile_emulation)
            # 开启代理
            # if self.precise and self._proxy:
            #     if MESSAGE_DEBUG_SWITCH:
            #         logger.debug('添加浏览器代理！')
            #     options.add_argument('--proxy-server={0}'.format(self._proxy.proxy))
            # 设置浏览器安装路径
            if self._binary_location:
                options.binary_location = self._binary_location
            _driver = webdriver.HSChrome(self._webdriver_path, chrome_options=options)
        elif self.browser_type.lower() == 'ie':
            # 设置driver路径
            if self._webdriver_path is None:
                # 判断系统是32bit还是64bit
                osbit = platform.architecture()[0]
                if osbit == '64bit':
                    exepath = os.path.join(TOOL_FLODER_PATH, r'IEDriverServer_x64', r'IEDriverServer.exe')
                else:
                    exepath = os.path.join(TOOL_FLODER_PATH, r'IEDriverServer_win32', r'IEDriverServer.exe')
                self._webdriver_path = os.path.abspath(exepath)
                os.environ["webdriver.driver"] = self._webdriver_path
            _driver = webdriver.HSIe(executable_path=self._webdriver_path)
        else:
            message = '请确认初始化表格中，浏览器类型是否书写正确，目前只支持：ie、firefox和chrome'
            raise CustomException(CustomError.Error_EQ03005000_Browser_Type_InCorrect, extra_msg=message)
        if self.browser_type.lower() == 'chrome' and options.debugger_address:
            #则不执行窗口最大化操作
            pass
        else:
            _driver.maximize_window()
        globals()[self.driver_url_no] = _driver.command_executor._url
        globals()[self.driver_session_no] = _driver.session_id
        globals()[self.last_browser_type_no] = self.browser_type
        globals()[self.driver_no] = _driver
        self.__sync_info()
        return _driver

    def get_driver(self, save_as=0, download=None, mobile_type=None, profile_dir=None):
        '''
        打开浏览器网页，并获取driver对象

        :Args:
         - save_as: 另存为方式，默认值是0，静默保存
         - download: 保存的路径，默认使用浏览器默认保存路径
         - mobile_type: chrome的手机模式，默认为浏览器模式

        :Returns:
            返回webdriver对象

        :Example:
         - 例1: WebDriverFactory('firefox','firefox1').get_driver()
         - 例2: WebDriverFactory('chrome','chrome1').get_driver(download='D:')
        '''
        # 判断浏览器类型与上一个脚本是否不一致
        if (self.last_browser_type and
                self.last_browser_type == self.browser_type):
            # 判断是否已有浏览器
            if self.driver_url and self.driver_session:
                # self._driver = ReuseRemote(
                #     command_executor=self.driver_url,
                #     session_id=self.driver_session)
                #确定浏览器是否打开
                try:
                    #用获取title的方式确定，浏览器是否还正常开启
                    title = self._driver.title
                    if MESSAGE_DEBUG_SWITCH:
                        logger.debug(type(self._driver))
                    return self._driver
                except WebDriverException as msg:
                    #获取浏览器失败，把已经关闭了浏览器的driver关掉, 然后重新启动driver
                    self.close()

        self._driver = self.__create_driver(save_as, download, mobile_type, profile_dir)
        return self._driver

    def restart_driver(self, save_as=0, download=None, mobile_type=None):
        '''
        重新打开浏览器网页，并获取driver对象

        :Args:
         - save_as: 另存为方式，默认值是0，静默保存
         - download: 保存的路径，默认使用浏览器默认保存路径
         - mobile_type: chrome的手机模式，默认为浏览器模式

        :Returns:
            返回webdriver对象

        :Example:
         - 例1: WebDriverFactory('firefox','firefox1').restart_driver()
         - 例2: WebDriverFactory('chrome','chrome1').restart_driver(download='D:')
        '''
        # self.precise = web_config.is_web_proxy
        # self._proxy_switch = self.precise
        self._driver = self.__create_driver(save_as, download, mobile_type)
        return self._driver

    def close(self):
        '''
        关闭浏览器及代理

        :Example:
         - 例: WebDriverFactory('firefox','firefox1').close()
        '''
        if self._driver is None:
            if self.driver_url and self.driver_session:
                # self._driver = ReuseRemote(
                #     command_executor=self.driver_url,
                #     session_id=self.driver_session)
                pass
            else:
                return
        self._driver.quit()
        globals().pop(self.driver_url_no)
        globals().pop(self.driver_session_no)
        globals().pop(self.driver_no)
        self.driver_url = ''
        self.driver_session = ''
        self.last_browser_type = ''
        self._driver = ''
        # self._server = ''
        # self.__stop_proxy_server()

        try:
            web_config.last_url = ''
            web_config.last_login_name = ''
            web_config.last_menu = ''
            web_config.last_browser_type = ''

            # web_config_bl.last_url =""
            # web_config_bl.last_login_name = ''
            # web_config_bl.last_menu = ''
            # web_config_bl.last_browser_type = ''

            web_config_secondary.last_url=''
            web_config_secondary.last_login_name = ''
            web_config_secondary.last_menu = ''
            web_config_secondary.last_browser_type = ''

            web_config_acpt.last_url = ''
            web_config_acpt.last_login_name = ''
            web_config_acpt.last_menu = ''
            web_config_acpt.last_browser_type = ''

            # web_config_bl2.last_url = ''
            # web_config_bl2.last_login_name = ''
            # web_config_bl2.last_menu = ''
            # web_config_bl2.last_browser_type = ''
        except:
            pass

    def set_driver(self, driver, driver_name="chrome"):
        '''
        设置webdriver对象

        :Args:
         - driver: webdriver对象
        '''
        if driver_name:
            self.browser_type = driver_name
        else:
            if 'chrome' in driver.name:
                self.browser_type = 'chrome'
            elif 'firefox' in driver.name:
                self.browser_type = 'firefox'
            elif 'ie' in driver.name:
                self.browser_type = 'ie'

        globals()[self.driver_url_no] = driver.command_executor._url
        globals()[self.driver_session_no] = driver.session_id
        globals()[self.driver_no] = driver
        globals()[self.last_browser_type_no] = self.browser_type

        self._driver = webdriver.HSWebDriver(command_executor=driver.command_executor._url
                                             , desired_capabilities={}
                                             , is_convert_driver=True
                                             , session_id=driver.session_id)

        self.__sync_info()
        return self._driver

    def set_webdriver_path(self, exepath):
        '''
        设置webdriver程序的文件路径

        :Args:
         - exepath: webdriver程序的文件路径

        :Example:
         - 例: WebDriverFactory('chrome','chrome1').set_webdriver_path('D:\chromedriver.exe')
        '''
        if os.path.exists(exepath):
            self._webdriver_path = os.path.abspath(exepath)
            os.environ['webdriver.driver'] = self._webdriver_path
        else:
            raise FileNotFoundError('webdriver程序路径不存在！')

    def set_binary_location(self, exepath):
        '''
        设置浏览器程序文件路径

        :Args:
         - exepath: 浏览器程序文件路径

        :Example:
         - 例: WebDriverFactory('chrome','chrome1').set_binary_location('D:/chrome.exe')
        '''
        if os.path.exists(exepath):
            self._binary_location = os.path.abspath(exepath)
            os.environ["webdriver.bin"] = self._binary_location
        else:
            raise FileNotFoundError('浏览器程序路径不存在！')

    def set_chrome_options(self, options):
        '''
        设置chrome的浏览器参数


        :Args:
         - options: chrome浏览器设置

        :Example:
         - 例: WebDriverFactory('chrome','chrome1').set_chrome_options(webdriver.ChromeOptions())
        '''
        if isinstance(options, webdriver.ChromeOptions):
            self._chrome_options = options

    def get_driver_list(self):
        '''
        获取当前webdriver工厂创建的所有driver列表

        :Returns:
            当前webdriver工厂创建的driver列表
        '''
        driver_list = list()
        for key, value in globals().items():
            if 'driver_' in key and 'driver_url_' not in key and 'driver_session_' not in key:
                driver_list.append({key[7:]:value})
        return driver_list

    def get_proxy_list(self):
        '''
        获取当前webdriver工厂创建的所有proxy列表

        :Returns:
            当前webdriver工厂创建的proxy列表
        '''
        warnings.warn("此方法已被废弃", DeprecationWarning);
        proxy_list = list()
        for key, value in globals().items():
            if 'proxy_' in key:
                proxy_list.append({key[6:]: value})
        return proxy_list
